/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.kylingroup.JavaFX.ListView;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.InvalidationListener;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.SelectionMode;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

/**
 *
 * @author kylin
 */
public class TestListView2 extends Application{
    FileTransferItemList list=null;
    ListView<FileTransferItem> listView=null;
    @Override
    public void start(Stage primaryStage) throws Exception{
        
        VBox box=new VBox();
        
        Button btnstart=new Button("start all");
        btnstart.setOnAction((ActionEvent event)->{
            Iterator itor=list.iterator();
            while(itor.hasNext()){
                FileTransferItem item=(FileTransferItem)itor.next();
                if(item.getTranfertask()!=null&&!item.isTransferstatus()){
                    new Thread(item.getTranfertask()).start();
                }else{
                    System.out.println(""+item.getLabelfile().getText()+"has finished");
                }
            }
        });
        
        
        Button btnload=new Button("initialize list");
        btnload.setOnAction((ActionEvent event)->{
            createContent();
        });
        
        listView=new ListView<FileTransferItem>();
        
        Button btnadd=new Button("add");
        btnadd.setOnAction((ActionEvent event)->{
            File source=new File("/home/kylin/Shared/KGFileuploader1.0.zip");
            String defaultpath=System.getProperty("user.home");
            int buffersize=1024;
            int sleeptime=1000;
        
            FileTransferItem item=new FileTransferItem();
            item.setTranfertask(new TransferTask(source,new File(defaultpath+"/kgplug_copy_new"+".zip"),buffersize,sleeptime));
            list.add(item);
            listView.setItems(list);
            listView.refresh();
        });
        
        box.getChildren().add(btnload);
        box.getChildren().add(listView);
        box.getChildren().add(btnadd);
        box.getChildren().add(btnstart);
        
        Scene scene=new Scene(box,400,500);
        scene.setFill(Color.LIGHTGRAY);
        
        primaryStage.setScene(scene);
        primaryStage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
    
    public void createContent(){
        
        if(list!=null&&!list.isEmpty()){
            list.removeAll(list);
            listView.refresh();
        }
        
        File source=new File("/home/kylin/Shared/KGFileuploader1.0.zip");
        String defaultpath=System.getProperty("user.home");
        int buffersize=1024;
        int sleeptime=1000;
        
        
        list=new FileTransferItemList();
//        for(int i=0;i<3;i++){
//            FileTransferItem item=new FileTransferItem();
//            item.setTranfertask(new TransferTask(source,new File(defaultpath+"/kgplug_copy"+i+".zip"),buffersize,sleeptime));
//            list.add(item);
//        }

        //listView.setItems(list);
        
        listView.setCellFactory((ListView<FileTransferItem> l) -> new FileTransferItemCell(list,listView));
        listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
        
        System.out.println("load list");
    }
}

class FileTransferItemList implements ObservableList<FileTransferItem>{
    private ArrayList<FileTransferItem> list=null;
    
    public FileTransferItemList(){
        list=new ArrayList<FileTransferItem>();
    }
    
    @Override
    public void addListener(ListChangeListener<? super FileTransferItem> listener) {
        
    }

    @Override
    public void removeListener(ListChangeListener<? super FileTransferItem> listener) {
        
    }

    @Override
    public boolean addAll(FileTransferItem... elements) {
        ArrayList list=new ArrayList();
        for(int i=0;i<elements.length;i++){
            list.add(elements[i]);
        }
        return this.addAll(list);
    }

    @Override
    public boolean setAll(FileTransferItem... elements) {
        ArrayList list=new ArrayList();
        for(int i=0;i<elements.length;i++){
            list.add(elements[i]);
        }
        return this.addAll(list);
    }

    @Override
    public boolean setAll(Collection<? extends FileTransferItem> col) {
        return this.addAll(col);
    }

    @Override
    public boolean removeAll(FileTransferItem... elements) {
        ArrayList list=new ArrayList();
        for(int i=0;i<elements.length;i++){
            list.add(elements[i]);
        }
        return this.removeAll(list);
    }

    @Override
    public boolean retainAll(FileTransferItem... elements){
        ArrayList list=new ArrayList();
        for(int i=0;i<elements.length;i++){
            list.add(elements[i]);
        }
        return this.retainAll(list);
    }

    @Override
    public void remove(int from, int to) {
        list.remove(to);
    }

    @Override
    public int size() {
        return list.size();
    }

    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return list.contains(o);
    }

    @Override
    public Iterator<FileTransferItem> iterator() {
        return list.iterator();
    }

    @Override
    public Object[] toArray() {
        return list.toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return list.toArray(a);
    }

    @Override
    public boolean add(FileTransferItem e) {
        return list.add(e);
    }

    @Override
    public boolean remove(Object o) {
        return list.remove(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return list.containsAll(c);
    }

    @Override
    public boolean addAll(Collection<? extends FileTransferItem> c) {
        return list.addAll(c);
    }

    @Override
    public boolean addAll(int index, Collection<? extends FileTransferItem> c) {
        return list.addAll(index, c);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return list.removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return list.retainAll(c);
    }

    @Override
    public void clear() {
        list.clear();
    }

    @Override
    public FileTransferItem get(int index) {
        return list.get(index);
    }

    @Override
    public FileTransferItem set(int index, FileTransferItem element) {
        return list.set(index, element);
    }

    @Override
    public void add(int index, FileTransferItem element) {
        list.add(index, element);
    }

    @Override
    public FileTransferItem remove(int index) {
        return list.remove(index);
    }

    @Override
    public int indexOf(Object o) {
        return list.indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        return list.lastIndexOf(o);
    }

    @Override
    public ListIterator<FileTransferItem> listIterator() {
        return list.listIterator();
    }

    @Override
    public ListIterator<FileTransferItem> listIterator(int index) {
        return list.listIterator(index);
    }

    @Override
    public List<FileTransferItem> subList(int fromIndex, int toIndex) {
       return list.subList(fromIndex, toIndex);
    }

    @Override
    public void addListener(InvalidationListener listener) {
 
    }

    @Override
    public void removeListener(InvalidationListener listener) {
     
    }

}

class FileTransferItem{
    private HBox box=null;
    private Label labelfile=null;
    private Label labelinfo=null;
    private ImageView btnstart=null;
    private ProgressIndicator indicator=null;
    private TransferTask tranfertask=null;
    private boolean transferstatus=false;
    
    public FileTransferItem(){
        box=new HBox();
        box.setAlignment(Pos.CENTER_LEFT);
        ImageView icon=new ImageView(new Image(getClass().getResourceAsStream("file.png")));
        labelfile=new Label("");
        labelfile.setGraphic(icon);
        labelfile.setPadding(new Insets(0,50,0,10));
        labelinfo=new Label("ready to transfer");
        labelinfo.setPadding(new Insets(0,10,0,10));
        btnstart=new ImageView(new Image(getClass().getResourceAsStream("start.png")));
        indicator=new ProgressIndicator();
        indicator.setPrefSize(30, 30);
        indicator.setPadding(new Insets(0,5,0,5));
        
        
        box.getChildren().add(labelfile);
        box.getChildren().add(labelinfo);
        box.getChildren().add(indicator);
        box.getChildren().add(btnstart);
        
    }

    public HBox getBox() {
        return box;
    }

    public Label getLabelfile() {
        return labelfile;
    }

    public Label getLabelinfo() {
        return labelinfo;
    }

    public ProgressIndicator getIndicator() {
        return indicator;
    }
    
    public ImageView getBtnstart() {
        return btnstart;
    }
    
    public Task getTranfertask() {
        return tranfertask;
    }
    
    public void setTranfertask(TransferTask tranfertask) {
        this.tranfertask = tranfertask;
        File file=this.tranfertask.getSource();
        labelfile.setText(file.getName()+" size("+file.length()+" bytes)");
        indicator.setProgress(0);
        indicator.progressProperty().bind(this.tranfertask.progressProperty());
        this.tranfertask.addEventHandler(WorkerStateEvent.WORKER_STATE_SUCCEEDED,new EventHandler<WorkerStateEvent>(){
            @Override
            public void handle(WorkerStateEvent event) {
                transferstatus=true;
                labelinfo.setText("transfer succed.");
            }        
        });
    }
    
    public boolean isTransferstatus() {
        return transferstatus;
    }
}

class FileTransferItemCell extends ListCell<FileTransferItem>{
    private ContextMenu addMenu=new ContextMenu();
    FileTransferItemList list=null;
    ListView<FileTransferItem> listView;
    
    public FileTransferItemCell(FileTransferItemList list,ListView<FileTransferItem> listView){
        this.list=list;
        this.listView=listView;
        MenuItem addMenuItem = new MenuItem("unselect");
        addMenu.getItems().add(addMenuItem);
        addMenuItem.setOnAction(new EventHandler(){
            public void handle(Event t){
                System.out.println("[info]:"+FileTransferItemCell.this.getItem().getLabelfile().getText());
                list.remove(FileTransferItemCell.this.getItem());
                listView.refresh();
            }
        });
    }
    @Override
    public void updateItem(FileTransferItem item,boolean empty){
        super.updateItem(item, empty);
        if(empty){
            this.setText(null);
            this.setGraphic(null);
        }else{
            setContextMenu(addMenu);
            this.setGraphic(item.getBox());
            
            item.getBtnstart().setOnMouseClicked(new EventHandler<MouseEvent>(){
                @Override
                public void handle(MouseEvent event){
                    if(item.getTranfertask()!=null&&!item.isTransferstatus()){
                        new Thread(item.getTranfertask()).start();
                    }
                }
            });
            
        }
    }
}

class TransferTask extends Task{
    
    public File source=null;
    public File target=null;
    private int sleep=0;
    private int buffersize=0;
    //private HashMap<String,String> info=null;

    public File getSource() {
        return source;
    }

    public File getTarget() {
        return target;
    }
    
    public TransferTask(File source,File target,int buffersize,int sleep){
        this.source=source;
        this.target=target;
        this.buffersize=buffersize;
        this.sleep=sleep;
        //info=new HashMap<String,String>();
        System.out.println(target.getAbsolutePath());
    }

    @Override
    protected Object call() throws Exception {
                 
        FileInputStream in=new FileInputStream(source);
        FileOutputStream out=new FileOutputStream(target);
                
        byte[] buffer=new byte[buffersize];
        long size=source.length();
        long starttime=new Date().getTime();

        int ins=0;
        int rlength=0;
        while((ins= in.read(buffer, 0, buffer.length)) != -1){            
            out.write(buffer,0,ins);
            rlength+=ins;
            updateProgress(rlength,size);
            Thread.sleep(sleep);
        }
        in.close();
        out.flush();
        out.close();
        
        long endtime=new Date().getTime()-starttime;
        
        return null;
    }
}